package com.lantu.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lantu.constant.CommonConstants;
import com.lantu.constant.RedisKeyConstants;
import com.lantu.core.entity.User;
import com.lantu.dto.member.MemberDTO;
import com.lantu.core.entity.Member;
import com.lantu.core.mapper.MemberMapper;
import com.lantu.core.service.IMemberService;
import com.lantu.dto.member.MemberLoginDTO;
import com.lantu.dto.member.MemberPageDTO;
import com.lantu.pojo.member.LoginMember;
import com.lantu.utils.BeanUtils;
import com.lantu.utils.JwtUtils;
import com.lantu.utils.RedisUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author binyuhuang
 * @since 2023-02-07
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {
    @Resource
    private RedisUtil redisUtil;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private MemberMapper mapper;

    @Override
    public Map<String, Object> login(HttpServletRequest request, MemberLoginDTO dto) throws Exception {
        // 根据用户名查询
        Member member = getMemberByUsername(dto.getUsername());
        if (ObjectUtil.isNotEmpty(member) && StrUtil.isNotEmpty(member.getId())) {
            if (member.getDeleted() != 0) {
                throw new Exception("用户不存在");
            }

            if (!Objects.equals(member.getStatus(), CommonConstants.MEMBER_NORMAL_STATUS)) {
                throw new Exception("用户已禁用");
            }

            // 结果不为空，并且密码和传入密码匹配，则生成token，并将用户信息存入redis
            if (passwordEncoder.matches(dto.getPassword(), member.getPassword())) {
                // jwt生成token
                String key = jwtUtils.generateToken(member.getId());

                //更新会员最近登录时间和最近登录ip
                this.updateById(member.updateByLogin(request));

                // 存入redis
                redisUtil.set(RedisKeyConstants.MEMBER_TOKEN + key, LoginMember.newInstance(member), CommonConstants.DEFAULT_USER_TOKEN_TIMEOUT);

                // 返回数据
                Map<String, Object> data = new HashMap<>();
                data.put("token", key);
                return data;
            }
        }
        return null;
    }

    /*@Override
    public Map<String, Object> login(User user) {
        // 根据用户名和密码查询
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername,user.getUsername());
        wrapper.eq(User::getPassword,user.getPassword());
        User loginUser = this.baseMapper.selectOne(wrapper);
        // 结果不为空，则生成token，并将用户信息存入redis
        if(loginUser != null){
            // 暂时用UUID, 终极方案是jwt
            String key = "user:" + UUID.randomUUID();

            // 存入redis
            loginUser.setPassword(null);
            redisTemplate.opsForValue().set(key,loginUser,30, TimeUnit.MINUTES);

            // 返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("token",key);
            return data;
        }
        return null;
    }*/

    @Override
    public Map<String, Object> getUserInfo(String token) {
        // 根据token获取用户信息，redis
        Object obj = redisUtil.get(token.startsWith(RedisKeyConstants.MEMBER_TOKEN) ? token : RedisKeyConstants.MEMBER_TOKEN + token);
        if (ObjectUtil.isNotEmpty(obj)) {
            Member loginMember = BeanUtils.toBean(obj, Member.class);
            Map<String, Object> data = new HashMap<>();
            data.put("name", loginMember.getUsername());
            data.put("avatar", loginMember.getAvatar());
            return data;
        }
        return null;
    }

    @Override
    public void logout(String token) {
        if(StrUtil.isNotEmpty(token)){
            token = token.startsWith(RedisKeyConstants.MEMBER_TOKEN) ? token : RedisKeyConstants.MEMBER_TOKEN + token;
            if(redisUtil.hasKey(token))redisUtil.delteKey(token);
        }
    }

    @Override
    public boolean addMember(User loginUser, MemberDTO dto) {
        Member newMember = BeanUtils.toBean(dto, Member.class, "password");
        newMember.setPassword(passwordEncoder.encode(dto.getPassword()));
        newMember.createBy(loginUser.getUsername());
        return this.save(newMember);
    }

    @Override
    public boolean updateMember(User loginUser, MemberDTO dto) {
        Member sourceMember = this.getById(dto.getId());
        if(ObjectUtil.isNotEmpty(sourceMember) && StrUtil.isNotEmpty(sourceMember.getId())){
            sourceMember = BeanUtils.toBean(dto, Member.class, "password");
            if(StrUtil.isNotEmpty(dto.getPassword())){
                sourceMember.setPassword(passwordEncoder.encode(dto.getPassword()));
            }
            sourceMember.updateBy(loginUser.getUsername());
            return this.updateById(sourceMember);
        }
        return false;
    }

    @Override
    public Member getMemberByUsername(String username) {
        if (StrUtil.isNotEmpty(username)) {
            List<Member> list = this.lambdaQuery()
                    .eq(Member::getUsername, username)
                    .list();
            if (CollUtil.isNotEmpty(list)) {
                return CollUtil.getFirst(list);
            }
        }
        return null;
    }

    @Override
    public Page<Member> getMemberPage(MemberPageDTO dto) {
        if(ObjectUtil.isNull(dto)){
            return new Page<>();
        }
        return mapper.selectPage(dto);
    }
}
